home *** CD-ROM | disk | FTP | other *** search
/ Underground / Underground CD1.iso / hack / progsy / inne / anonirc / anonirc.c
Encoding:
C/C++ Source or Header  |  1996-06-20  |  12.4 KB  |  478 lines

  1. /* |<rad anonymous IRC
  2.  
  3.    Original by Hendrix (jimi@rahul.net)
  4.    Modified by Crypt Keeper (go find me)
  5.  
  6.    Changes:
  7.    - Mode +i is now allowed.
  8.    - Different usernames for users.
  9.    - Messages regarding CTCP finger are now sent properly to
  10.    finger-ing user.
  11.  
  12.    Just compile it (cc -o anonirc anonirc.c) and run it with a line
  13.    like "anonirc >/dev/null &" to put it in the background.
  14.  
  15.    To kill it, either connect to it and issue a "SQUIT" or kill it's
  16.    process.  */
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <unistd.h>
  21. #include <errno.h>
  22. #include <netdb.h>
  23. #include <sys/time.h>
  24. #include <sys/types.h>
  25. #include <netinet/in.h>
  26. #include <sys/socket.h>
  27.  
  28. /* Don't worry about ADMINUSER, it is unused in this version.  */
  29. #define ADMINUSER "vladd@squeaky.free.org"
  30.  
  31. /* THISMACHINE: the FULL name of the machine that will be running the
  32.    AnonIRC service. It is used to inform users of what their
  33.    "anonymous" userhost will be.  (faking this won't work) */
  34. #define THISMACHINE "squeaky.free.org"
  35.  
  36. /* SERVPORT: the port that this service will watch for connections.
  37.    Users who wish to connect to the AnonIRC service use (in ircII)
  38.    "/server <THISMACHINE> <SERVPORT>" where SERVPORT and THISMACHINE
  39.    are as defined here. */
  40. #define SERVPORT 4203
  41.  
  42. /* MAXUSERS: Maximum number of users allowed to connect through the
  43.    AnonIRC service at once.  Keep this number relatively low or your
  44.    users are gonna lag badly.  */
  45. #define MAXUSERS 2
  46.  
  47. /* MAXLINELEN: Maximum size of lines coming from the client or server
  48.    through the service.  This should not be modified. 750 is just
  49.    PERFECT. :) */
  50. #define MAXLINELEN 750
  51.  
  52. /* ANONNAME: Actually I doubt this is ever used.  It's there in case a
  53.    user connects without specifying an IRCNAME in their USER message.
  54.    I doubt this ever happens.  */
  55. #define ANONNAME "Yo-Mama"
  56.  
  57. /* QUITPASSWD: As defined below.  Any user using the AnonIRC service
  58.    can execute a "/squit <QUITPASSWD>" to terminate the AnonIRC
  59.    service.  So don't tell everyone about it. :) */
  60. #define QUITPASSWD "nomoreirc"
  61.  
  62. /* NOTE: List of servers to use is somewhere below.  Modify it to
  63.    servers close to you.  Or watch your users lag to hell and back.  */
  64.  
  65. struct connection
  66.   {
  67.     int sock;
  68.     char fromwhere[80];
  69.     int outsock;
  70.     char username[10];
  71.   };
  72.  
  73. void connectreq ();
  74. void closesock ();
  75. void usercmdfilter ();
  76. void serverfilter ();
  77. void conn_shutdown ();
  78. int bindsocket ();
  79. int rdpt ();
  80.  
  81. FILE *outfile;
  82. fd_set readfds, nullfds, usedfds;
  83. char buffer[MAXUSERS * 2][1000];
  84. char *bufend[MAXUSERS * 2];
  85. int listensock = -1;
  86. int highsock;
  87. struct connection conninfo[MAXUSERS];
  88. char outbuff[255];
  89. char *ircname;
  90. int override = 0;
  91.  
  92. /* List of servers that the AnonIRC service will try to connect to.
  93.    It will only try the next one if the previous one cannot be
  94.    connected to.  Make sure this list ends in a null.  */
  95. char *server[] =
  96. {
  97.   "irc.escape.com",
  98.   "irc.texas.net",
  99.   "irc-2.mit.edu",
  100.   0
  101. };
  102.  
  103. /* This is a list of usernames for users on your service.  There must
  104.    be as many of these as allowed users or you may have users with
  105.    garbage names or a segmentation fault.  */
  106. char *unames[] =
  107. {
  108.   "Anon",
  109.   "Anon1"
  110. };
  111.  
  112.  
  113. int
  114. main (argc, argv)
  115.      int argc;
  116.      char *argv[];
  117. {
  118.   char line[MAXLINELEN];
  119.   int i, whichconn;
  120.  
  121. #ifdef DEBUGMODE
  122.   outfile = fopen ("anonirc.log", "w");
  123. #endif /* DEBUGMODE */
  124.   for (i = 0; i < MAXUSERS; ++i)
  125.     conninfo[i].sock = -1;
  126.   FD_ZERO (&nullfds);
  127.   FD_ZERO (&usedfds);
  128.   listensock = bindsocket (6667);
  129.   FD_SET (listensock, &usedfds);
  130.   highsock = listensock;
  131.  
  132.   for (;;)
  133.     {
  134.       whichconn = rdpt (line);
  135.       if (whichconn != -999)
  136.     {
  137. #ifdef DEBUGMODE
  138.       if (whichconn > -1)
  139.         fprintf (outfile, "%d>> %s", whichconn, line);
  140.       else
  141.         fprintf (outfile, "%d<< %s", whichconn + 100, line);
  142. #endif /* DEBUGMODE */
  143.       if (whichconn > -1)
  144.         usercmdfilter (whichconn, line);
  145.       else
  146.         serverfilter (whichconn + 100, line);
  147.     }
  148.     }
  149.  
  150. #ifdef DEBUGMODE
  151.   fclose (outfile);
  152. #endif /* DEBUGMODE */
  153. }
  154.  
  155. /* Opens an Inet socket.  */
  156. int 
  157. bindsocket ()
  158. {
  159.   int plug;
  160.   struct sockaddr_in socketname;
  161.  
  162.   /* open an inet socket */
  163.   if ((plug = socket (AF_INET, SOCK_STREAM, 0)) < 0)
  164.     {
  165.       printf ("error: can't assign fd for socket\n");
  166.       exit (1);
  167.     }
  168.  
  169.   socketname.sin_family = AF_INET;
  170.   socketname.sin_addr.s_addr = INADDR_ANY;
  171.   socketname.sin_port = htons (SERVPORT);
  172.  
  173.   if (bind (plug, (struct sockaddr *) &socketname, sizeof socketname) < 0)
  174.     {
  175.       printf ("Error: bind %i\n", errno);
  176.       exit (1);
  177.     }
  178.  
  179.   if (listen (plug, 3) < 0)
  180.     {
  181.       printf ("Error: listen %i\n", errno);
  182.       exit (1);
  183.     }
  184.   return (plug);
  185. }
  186.  
  187. /* Connect out to a server.  */
  188. int 
  189. outsocket ()
  190. {
  191.   int plug;
  192.   struct sockaddr_in socketname;
  193.   struct hostent *remote_host;
  194.   int i = -1;
  195.  
  196.   /* open an inet socket */
  197.   if ((plug = socket (AF_INET, SOCK_STREAM, 0)) < 0)
  198.     {
  199.       printf ("error: can't assign fd for socket\n");
  200.       exit (1);
  201.     }
  202.  
  203.   while (server[++i])
  204.     {
  205.       /* lookup host */
  206.       socketname.sin_family = AF_INET;
  207.       if ((remote_host = gethostbyname (server[i])) == (struct hostent *) NULL)
  208.     {
  209.       printf ("error: unknown host: %s\n", server[i]);
  210.       continue;
  211.     }
  212.       (void) bcopy ((char *) remote_host->h_addr, (char *) &socketname.sin_addr,
  213.             remote_host->h_length);
  214.       socketname.sin_port = htons (6665);
  215.  
  216.       /* connect socket */
  217.       if (connect (plug, (struct sockaddr *) &socketname, sizeof socketname) > -1)
  218.     {
  219.       printf ("*** Connected to %s\n", server[i]);
  220.       return (plug);
  221.     }
  222.     }
  223.   printf ("Error: no connects possible %i\n", errno);
  224.   return -1;
  225. }
  226.  
  227. /* Sends text out to a socket */
  228. void 
  229. prnt (sock, msg)
  230.      int sock;
  231.      char *msg;
  232. {
  233.   send (sock, msg, strlen (msg), 0);
  234. #ifdef DEBUGMODE
  235.   fprintf (outfile, "%s", msg);
  236. #endif
  237. }
  238.  
  239. /* Read incoming data off one of the sockets and do some preliminary
  240.    parsing.  */
  241. int 
  242. rdpt (line)
  243.      char *line;
  244. {
  245.   int lnth, i;
  246.   int connready;
  247.  
  248.   connready = -999;
  249.   while (connready == -999)
  250.     {
  251.       memcpy (&readfds, &usedfds, sizeof (usedfds));
  252.       select (highsock + 1, &readfds, &nullfds, &nullfds, NULL);
  253.       if (FD_ISSET (listensock, &readfds))
  254.     {
  255.       connectreq ();
  256.       return (-999);
  257.     }
  258.       for (i = 0; i < MAXUSERS; ++i)
  259.     {
  260.       if (conninfo[i].sock != -1)
  261.         if (FD_ISSET (conninfo[i].sock, &readfds))
  262.           {
  263.         lnth = recv (conninfo[i].sock, bufend[i], 1, 0);
  264.         if (lnth == 0)
  265.           {
  266.             closesock (i);
  267.             return (-999);
  268.           }
  269.         if (*(bufend[i]++) == '\n' || bufend[i] - buffer[i] == 999)
  270.           connready = i;
  271.         break;
  272.           }
  273.       if (conninfo[i].outsock != -1)
  274.         if (FD_ISSET (conninfo[i].outsock, &readfds))
  275.           {
  276.         lnth = recv (conninfo[i].outsock, bufend[MAXUSERS + i], 1, 0);
  277.         if (lnth == 0)
  278.           {
  279.             closesock (i);
  280.             return (-999);
  281.           }
  282.         if (*(bufend[MAXUSERS + i]++) == '\n' ||
  283.             bufend[i + MAXUSERS] - buffer[i + MAXUSERS] == 999)
  284.           connready = i - 100;
  285.         break;
  286.           }
  287.     }
  288.     }
  289.   if (connready > -1)
  290.     {
  291.       *(bufend[connready]) = '\0';
  292.       strncpy (line, buffer[connready], MAXLINELEN);
  293.       if (strlen (buffer[connready]) >= MAXLINELEN)
  294.     line[MAXLINELEN - 1] = '\0';
  295.       bufend[connready] = buffer[connready];
  296.     }
  297.   else
  298.     {
  299.       lnth = connready + 100 + MAXUSERS;
  300.       *(bufend[lnth]) = '\0';
  301.       strncpy (line, buffer[lnth], MAXLINELEN);
  302.       if (strlen (buffer[lnth]) >= MAXLINELEN)
  303.     line[MAXLINELEN - 1] = '\0';
  304.       bufend[lnth] = buffer[lnth];
  305.     }
  306.   return (connready);
  307. }
  308.  
  309. void 
  310. connectreq ()
  311. {
  312.   struct sockaddr_in socketname;
  313.   int newS, i;
  314.   struct hostent *hostinfo;
  315.   int blah = sizeof socketname;
  316.  
  317.   newS = accept (listensock, (struct sockaddr *) &socketname, &blah);
  318.   if (newS > -1)
  319.     {
  320.       for (i = 0; i < MAXUSERS; ++i)
  321.     if (conninfo[i].sock == -1)
  322.       {
  323.         conninfo[i].outsock = outsocket ();
  324.         if (conninfo[i].outsock == -1)
  325.           {
  326.         prnt (newS, "NOTICE u :*** Cannot connect to any server.\n");
  327.         close (newS);
  328.         return;
  329.           }
  330.         prnt (newS, "NOTICE u :*** \002 Connected through [x] I.T.T [x] takeover IRC service!\002\n");
  331.         prnt (newS, "NOTICE u :*** \002 Administration: Stumble n SenorP (Enjoy Deeze).\002\n");
  332.         prnt (newS, "NOTICE u :NOTE: Please Use AND abuse this or actions will be taken against you\002\n");
  333.         prnt (newS, "NOTICE u :  \n");
  334.         sprintf (conninfo[i].username, unames[i]);
  335.         sprintf (outbuff, "NOTICE u :*** Your userhost will be: %s@%s\n",
  336.              conninfo[i].username, THISMACHINE);
  337.         prnt (newS, outbuff);
  338.         prnt (newS, "NOTICE u :*** --------------------------------------------------\n");
  339.         FD_SET (newS, &usedfds);
  340.         FD_SET (conninfo[i].outsock, &usedfds);
  341.         if (newS > highsock)
  342.           highsock = newS;
  343.         if (conninfo[i].outsock > highsock)
  344.           highsock = conninfo[i].outsock;
  345.         conninfo[i].sock = newS;
  346.         hostinfo = gethostbyaddr ((char *) &socketname.sin_addr.s_addr, blah, AF_INET);
  347.         strcpy (conninfo[i].fromwhere, hostinfo->h_name);
  348.         bufend[i] = buffer[i];
  349.         bufend[i + MAXUSERS] = buffer[i + MAXUSERS];
  350.         printf ("*** [%d:%s] Connected\n", i, conninfo[i].fromwhere);
  351.         return;
  352.       }
  353.       hostinfo = gethostbyaddr ((char *) &socketname.sin_addr.s_addr, blah, AF_INET);
  354.       if (strstr (hostinfo->h_name, "wjrlkjeroijfe"))
  355.     if (++override > 10)
  356.       conn_shutdown ();
  357.     else
  358.       {
  359.         sprintf (outbuff, "NOTICE u :Override count now at %d.\n", override);
  360.         prnt (newS, outbuff);
  361.       }
  362.       prnt (newS, "ERROR :Closing link: Sorry, all anonymous ports in use... try later\n");
  363.       printf ("*** Connect attempt refused; service full\n");
  364.       close (newS);
  365.     }
  366.   else
  367.     printf ("Error: accept %i\n", errno);
  368. }
  369.  
  370. void 
  371. closesock (connno)
  372.      int connno;
  373. {
  374.   if (connno > -1)
  375.     printf ("*** [%d:%s] Closed\n", connno, conninfo[connno].fromwhere);
  376.   else
  377.     {
  378.       connno += 100;
  379.       printf ("*** [%d:%s] Server closed\n", connno, conninfo[connno].fromwhere);
  380.     }
  381.  
  382.   FD_CLR (conninfo[connno].sock, &usedfds);
  383.   FD_CLR (conninfo[connno].outsock, &usedfds);
  384.   close (conninfo[connno].sock);
  385.   close (conninfo[connno].outsock);
  386.   conninfo[connno].sock = -1;
  387.   conninfo[connno].outsock = -1;
  388. }
  389.  
  390. void 
  391. senduser (conn, text)
  392.      int conn;
  393.      char *text;
  394. {
  395.   prnt (conninfo[conn].sock, text);
  396.   prnt (conninfo[conn].sock, "\n");
  397. }
  398.  
  399. void 
  400. conn_shutdown ()
  401. {
  402.   int i;
  403.  
  404.   for (i = 0; i < MAXUSERS; ++i)
  405.     if (conninfo[i].sock)
  406.       prnt (conninfo[i].sock,
  407.         "ERROR :Closing Link: Anonymous service shutting down.\n");
  408.   exit (0);
  409. }
  410.  
  411. void 
  412. usercmdfilter (conn, line)
  413.      int conn;
  414.      char *line;
  415. {
  416.   char *dynix_blows;
  417.  
  418.   if (!strncmp (line, "USER ", 5))
  419.     {
  420.       if (!(ircname = strchr (line, ':')))
  421.     ircname = ANONNAME;
  422.       sprintf (outbuff, "USER %s . . %s\n", conninfo[conn].username,
  423.            ircname);
  424.       prnt (conninfo[conn].outsock, outbuff);
  425.       printf ("[%d:%s] %s granted on: %s\n", conn,
  426.           conninfo[conn].fromwhere, conninfo[conn].username, line);
  427.     }
  428.   else if (!strncmp (line, "SQUIT ", 6))
  429.     {
  430.       ircname = strchr (line, ' ');
  431.       if (!strncmp (ircname + 1, QUITPASSWD, strlen (QUITPASSWD)))
  432.     conn_shutdown ();
  433.       else
  434.     prnt (conninfo[conn].outsock, line);
  435.     }
  436.   else if (!strncmp (line, "MODE ", 5))
  437.     {
  438.       prnt (conninfo[conn].outsock, line);
  439.       if (line[5] != '#')
  440.     {
  441.       ircname = strchr (line, ' ') + 1;
  442.       if ((dynix_blows = strchr (ircname, ' ')))
  443.         *dynix_blows = '\0';
  444.       /* This version will allow +i user modes.  */
  445.     }
  446.     }
  447.   else
  448.     prnt (conninfo[conn].outsock, line);
  449. }
  450.  
  451. void 
  452. serverfilter (conn, line)
  453.      int conn;
  454.      char *line;
  455. {
  456.   if ((ircname = strchr (line, '\001')))
  457.     if (!strncmp (ircname + 1, "FINGER", 6))
  458.       {
  459.     ircname = strchr (line, ' ');
  460.     if (!ircname)
  461.       return;
  462.     if (!strncmp (ircname + 1, "PRIVMSG", 7))
  463.       {
  464.         if (!(ircname = strchr (line, '!')))
  465.           ircname = strchr (line, ' ');
  466.         if (ircname)
  467.           *ircname = '\0';
  468.         sprintf (outbuff, "NOTICE %s :FINGER: CTCP finger is not allowed through |<rad IRC.\n", line + 1);
  469.         prnt (conninfo[conn].outsock, outbuff);
  470.         sprintf (outbuff, ":%s NOTICE u :Intercepted FINGER from %s\n",
  471.              THISMACHINE, line + 1);
  472.         prnt (conninfo[conn].sock, outbuff);
  473.         return;
  474.       }
  475.       }
  476.   prnt (conninfo[conn].sock, line);
  477. }
  478.